home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / mig / Mig_RequestIdleHosts.c < prev    next >
C/C++ Source or Header  |  1990-09-24  |  8KB  |  298 lines

  1. /* 
  2.  * Mig_RequestIdleHosts.c --
  3.  *
  4.  *    Source code for the Mig_RequestIdleHosts procedure.
  5.  *    This procedure returns one or more idle hosts that may be
  6.  *    used for migration with a specified priority.
  7.  *
  8.  * Copyright 1990 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/lib/c/mig/RCS/Mig_RequestIdleHosts.c,v 2.4 90/09/24 14:46:49 douglis Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sprite.h>
  24. #include <mig.h>
  25. #include <host.h>
  26. #include <errno.h>
  27. #include <stdio.h>
  28. #include <status.h>
  29. #include "migInt.h"
  30.  
  31. extern int errno;
  32. extern char *strerror();
  33. extern char *malloc();
  34.  
  35. void (*migCallBackPtr)() = NULL;/* Procedure to call if idle hosts become
  36.                    available, or NULL. */
  37.  
  38. /*
  39.  * Define some state values to keep track of what we know about the
  40.  * global daemon.
  41.  *
  42.  * MIGD_OKAY    - we believe everything's okay.
  43.  * MIGD_WAITING    - waiting for the local migration daemon to talk to the global
  44.  *           daemon.
  45.  * MIGD_ERROR    - we've already hit an error and we don't want to announce 
  46.  *           further errors.
  47.  */
  48. typedef enum {
  49.     MIGD_OKAY,
  50.     MIGD_WAITING,
  51.     MIGD_ERROR,
  52. } MigdState;
  53.  
  54. /*
  55.  *----------------------------------------------------------------------
  56.  *
  57.  * StartMigd --
  58.  *
  59.  *    Fork a process to become the local migration daemon.
  60.  *
  61.  * Results:
  62.  *    0 for successful completion, -1 for error, in which case
  63.  *    errno indicates the nature of the error.  The parent
  64.  *    will return success as long as it can successfully fork.  That
  65.  *     doesn't necessarily mean the migration daemon has been started,
  66.  *    at least by the child, but the parent will go
  67.  *     ahead and try to contact the daemon again in any case.
  68.  *
  69.  * Side effects:
  70.  *    A new process is spawned and it tries to invoke migd.
  71.  *
  72.  *----------------------------------------------------------------------
  73.  */
  74.  
  75. static int
  76. StartMigd()
  77. {
  78.     int pid;
  79.     char *argArray[4];
  80.     
  81.     pid = fork();
  82.     if (pid < 0) {
  83.     fprintf(stderr, "couldn't fork\n");
  84.     return(-1);
  85.     }
  86.     if (pid > 0) {
  87.     /*
  88.      * We use the sprite Proc_Wait because we don't want to
  89.      * find out about any other children.
  90.      */
  91.     ReturnStatus status =
  92.         Proc_Wait(1, &pid, PROC_WAIT_BLOCK, (Proc_PID *) NULL,
  93.               (int *) NULL, (int *) NULL, (int *) NULL,
  94.               (Proc_ResUsage *) NULL);
  95.     if (status != SUCCESS) {
  96.         fprintf(stderr, "Error waiting for child to start migd: %s.",
  97.            Stat_GetMsg(status));
  98.         return(-1);
  99.     }
  100.     return(0);
  101.     }
  102.  
  103.     /*
  104.      * We are the child, and will try to become the migration daemon.
  105.      * First, sleep for just a moment so that we don't exit before our
  106.      * parent has waited for us... we don't want a user's signal handler to
  107.      * find out about us.  Then try to invoke migd.
  108.      */
  109.     sleep(1);
  110.     (void) system("/sprite/daemons/migd -D 2 -L");
  111.     exit(0);
  112. }
  113.  
  114.  
  115.  
  116.  
  117.  
  118. /*
  119.  *----------------------------------------------------------------------
  120.  *
  121.  * Mig_RequestIdleHosts --
  122.  *
  123.  *    Obtain one or more idle hosts from the migration server.
  124.  *    The caller specifies the number of hosts requested, the
  125.  *    priority at which they'll be used, flags to tell the daemon,
  126.  *    a callback procedure if a host is reclaimed or more hosts are
  127.  *    available, and an array to hold the identifiers of hosts.
  128.  *
  129.  * Results:
  130.  *    On error, -1 is returned, else the number of hosts in hostIDArray
  131.  *    is returned.  0 indicates no hosts were available.
  132.  *
  133.  * Side effects:
  134.  *      If the connection to the global server has not been opened, then
  135.  *    it is opened.  A callback is registered if one is specified.
  136.  *    If the local daemon isn't running, it is started.
  137.  *
  138.  *----------------------------------------------------------------------
  139.  */
  140. int
  141. Mig_RequestIdleHosts(numHosts, priority, flags, callBackPtr, hostArray)
  142.     int numHosts;        /* Number of hosts requested. */
  143.     int priority;        /* Priority of tasks; see mig.h */
  144.     int flags;            /* Flags for mig daemon; ditto. */
  145.     void (*callBackPtr)();    /* Procedure to call when getting
  146.                  * messages from mig daemon. */
  147.     int hostArray[];        /* Array of integers to fill with hostIDs. */
  148. {
  149.     Mig_IdleRequest request;
  150.     int virtualHost;
  151.     int physicalHost;
  152.     char *buffer;         /* Dynamically-allocated buffer for result
  153.                    of ioctl. */
  154.     unsigned int bufSize;    /* Size of buffer. */
  155.     int *intPtr;         /* Pointer into buffer. */
  156.     int i;            /* Counter. */
  157.     int status;            /* Status of system calls. */
  158.     int retries;        /* Count of retries if error during ioctl. */
  159.     int numWanted;        /* Number of hosts we wanted, set to
  160.                    numHosts. */
  161.     static MigdState migdState
  162.     = MIGD_OKAY;         /* We think migd is doing fine. */
  163.  
  164.  
  165. #ifdef DEBUG
  166.     fprintf(stderr, "Mig_RequestIdleHosts called.\n");
  167. #endif /* DEBUG */
  168.     if (mig_GlobalPdev < 0) {
  169.     if (MigOpenPdev(TRUE) < 0) {
  170. #ifdef DEBUG
  171.         fprintf(stderr, "Mig_RequestIdleHosts encountered error contacting global daemon.\n");
  172. #endif /* DEBUG */
  173.         return(-1);
  174.     }
  175.     }
  176.  
  177.  
  178.     if (!migGetNewHosts && !Mig_ConfirmIdle(0)) {
  179. #ifdef DEBUG
  180.     fprintf(stderr, "Mig_RequestIdleHosts -- no new hosts available.\n");
  181. #endif /* DEBUG */
  182.     return(0);
  183.     }
  184.     /*
  185.      * Tell the daemon what our physical host is so it doesn't try to tell
  186.      * us to migrate to this host.
  187.      */
  188.     status = Proc_GetHostIDs(&virtualHost, &physicalHost);
  189.     if (status != SUCCESS) {
  190.     errno = Compat_MapCode(status);
  191.     return(-1);
  192.     }
  193.  
  194.     request.numHosts = numHosts;
  195.     request.priority = priority;
  196.     request.flags = flags;
  197.     request.virtHost = virtualHost;
  198.  
  199.     bufSize = sizeof(int) * (1 + numHosts);
  200.     buffer = malloc(bufSize);
  201.     if (buffer == (char *) NULL) {
  202.     errno = ENOMEM;
  203.     return(-1);
  204.     }
  205.     for (retries = 2; retries >= 0; retries--) {
  206. #ifdef DEBUG
  207.     fprintf(stderr, "Mig_RequestIdleHosts starting ioctl.\n");
  208. #endif                /* DEBUG */
  209.     if (MigSetAlarm() < 0) {
  210.         fprintf(stderr,
  211.             "Error setting alarm for contact with migd.\n");
  212.         return(-1);
  213.     }
  214.     status = Fs_IOControl(mig_GlobalPdev, IOC_MIG_GETIDLE,
  215.                   sizeof(Mig_IdleRequest),
  216.                   (char *) &request,
  217.                   bufSize, buffer);
  218.     if (MigClearAlarm() < 0) {
  219.         fprintf(stderr,
  220.             "Error clearing alarm for contact with migd.\n");
  221.     }
  222. #ifdef DEBUG
  223.     fprintf(stderr, "Mig_RequestIdleHosts ioctl returned %x.\n", status);
  224. #endif                /* DEBUG */
  225.     if (status != SUCCESS) {
  226.         if (status == NET_NOT_CONNECTED) {
  227.         if (migdState == MIGD_OKAY) {
  228.             fprintf(stderr,
  229.                 "No migd daemon running on your host.  Waiting to see if it starts.\n");
  230.             migdState = MIGD_WAITING;
  231.             sleep(10);
  232.  
  233.         } else if (migdState == MIGD_WAITING) {
  234.             fprintf(stderr,
  235.                 "Starting a new migd.\n");
  236.             migdState = MIGD_ERROR;
  237.             if (StartMigd() < 0) {
  238.             return(0);
  239.             }
  240.             sleep(5);
  241.         }
  242.         }
  243.         close(mig_GlobalPdev);
  244.         mig_GlobalPdev = 0;
  245.         if (retries == 0 || MigOpenPdev(TRUE) < 0) {
  246.         if (migdState != MIGD_ERROR) {
  247.             fprintf(stderr,
  248.                 "Mig_RequestIdleHosts: error during ioctl to global master: %s\n",
  249.                 Stat_GetMsg(status));
  250.             migdState = MIGD_ERROR;
  251.         }
  252.         errno = Compat_MapCode(status);
  253.         free(buffer);
  254.         return(-1);
  255.         }
  256.     } else {
  257.         break;
  258.     }
  259.     }
  260.  
  261.     migdState == MIGD_OKAY;
  262.     intPtr = (int *) buffer;
  263.     numWanted = numHosts;
  264.     numHosts = *intPtr;
  265. #ifdef DEBUG_REQUEST
  266.     fprintf(stderr, "numHosts = %d\n", numHosts);
  267.     fflush(stderr);
  268. #endif /* DEBUG_REQUEST */
  269.  
  270.     intPtr++;
  271.  
  272.     for (i = 0; i < numHosts; i++) {
  273.     hostArray[i] = *intPtr;
  274.     (void) MigHostCache(*intPtr, MIG_CACHE_ADD, FALSE);
  275. #ifdef DEBUG
  276.     fprintf(stderr, "hostArray[%d] = %d\n", i, *intPtr);
  277.     fflush(stderr);
  278. #endif /* DEBUG */
  279.     intPtr++;
  280.     }
  281.  
  282.     free(buffer);
  283.     if (numHosts < numWanted) {
  284. #ifdef DEBUG
  285.     fprintf(stderr, "Mig_RequestIdleHosts didn't get enough hosts.\n");
  286. #endif /* DEBUG */
  287.     migGetNewHosts = 0;
  288.     }
  289.     if (callBackPtr != NULL) {
  290.     migCallBackPtr = callBackPtr;
  291.     }
  292. #ifdef DEBUG
  293.     fprintf(stderr, "Mig_RequestIdleHosts returning %d hosts.\n", numHosts);
  294. #endif /* DEBUG */
  295.     return(numHosts);
  296.     
  297. }
  298.